import datetime
import sys
from typing import List, Dict

from sqlalchemy import Boolean, Column, DateTime, String, Index, text, TEXT, distinct, or_
from sqlalchemy.orm import Session, relationship

from core.logger import logger
from common.database import Base
from common.database import SessionMixin
from app.auth.models.auth_permissions import AuthPermissions
from app.auth.models.auth_users_roles import AuthUsersRoles
from app.auth.models.auth_roles_permissions import AuthRolesPermissions

__all__ = ['AuthRoles']


class AuthRoles(Base, SessionMixin):
    """
    基于角色权限控制-角色表
    """
    __tablename__ = "auth_roles"
    role_name = Column(String(168), nullable=False, comment='角色名称')
    description = Column(String(168), nullable=False, comment='角色描述')
    auth_users = relationship('AuthUsers', secondary=AuthUsersRoles, back_populates='auth_roles', lazy='dynamic')
    auth_permissions = relationship('AuthPermissions', secondary=AuthRolesPermissions,
                                    back_populates='auth_roles', lazy='dynamic')
    create_time = Column(DateTime, default=datetime.datetime.now, nullable=False, comment="创建时间")
    update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, nullable=False,
                         comment="更新时间")

    __table_args__ = (
        Index('idx_auth_roles_uuid', 'uuid', unique=True),
        Index('idx_auth_roles_name', 'role_name', unique=True),
        Index('idx_auth_roles_uuid_description', 'uuid', 'description', unique=True),
        {
            'mysql_engine': 'innodb',
            'mysql_charset': 'utf8mb4',
            'mysql_collate': 'utf8mb4_unicode_ci',
            'extend_existing': True,
            'mysql_row_format': 'dynamic',
        }
    )

    def __repr__(self):
        return "<uuid='{}',role_name='{}'>".format(self.uuid, self.role_name)

    @classmethod
    def get_by_role_name(cls, db: Session, role_name: str) -> Dict:
        return db.query(cls).filter(cls.role_name == role_name).to_dict_first()

    @classmethod
    def get_by_uuid(cls, db: Session, uuid: str) -> Dict:
        return db.query(cls).filter(cls.uuid == uuid).to_dict_first()

    @classmethod
    def get_paginate(cls, db: Session, page: int, per_page: int, field: str, value: str) -> List[Dict]:
        try:
            search_field = []
            if value:
                for key, col in cls.__table__.c.items():
                    if field == "all" or key == field: search_field.append(col.like(f"%{value}%"))
            result = db.query(cls).filter(or_(*search_field)).paginate(page=page, per_page=per_page)
        except Exception as e:
            logger.error(f'{sys._getframe().f_code.co_name} {e}')
            return []

        result["fields"] = cls.get_display_field_meta()
        return result

    @classmethod
    def get_role_permissions_paginate(cls, db: Session, page, per_page, field, value) -> List[Dict]:
        data = cls.get_paginate(db, page, per_page, field, value)
        for item in data.get('items'):
            role = db.query(cls).filter(cls.uuid == item.get('uuid')).first()
            if role.auth_permissions:
                item.update({'role_permissions': sorted(
                    role.auth_permissions.with_entities(AuthPermissions.uuid, AuthPermissions.description).to_dict(),
                    key=lambda s: s.get('uuid'), reverse=False)})
            else:
                item.update({'role_permissions': []})
        return data
